package cn.stylefeng.guns.modular.business.frequency.financesettlement.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.stylefeng.guns.core.context.login.LoginContextHolder;
import cn.stylefeng.guns.core.exception.enums.StatusExceptionEnum;
import cn.stylefeng.guns.core.exception.ServiceException;
import cn.stylefeng.guns.core.factory.PageFactory;
import cn.stylefeng.guns.core.pojo.page.AndaPageResult;
import cn.stylefeng.guns.core.pojo.page.PageResult;
import cn.stylefeng.guns.core.pojo.response.ResponseData;
import cn.stylefeng.guns.modular.business.custom.constant.PublicCommon;
import cn.stylefeng.guns.modular.business.frequency.cmcity.mapper.CmCityMapper;
import cn.stylefeng.guns.modular.business.frequency.finance.model.result.ExcelHeaderInfo;
import cn.stylefeng.guns.modular.business.frequency.finance.model.result.PkgFinanceSettlement;
import cn.stylefeng.guns.modular.business.frequency.financecheck.entity.FinanceCheck;
import cn.stylefeng.guns.modular.business.frequency.financecheck.mapper.FinanceCheckMapper;
import cn.stylefeng.guns.modular.business.frequency.financesettlement.entity.FinanceSettlement;
import cn.stylefeng.guns.modular.business.frequency.financesettlement.mapper.FinanceSettlementMapper;
import cn.stylefeng.guns.modular.business.frequency.financesettlement.model.param.FinanceSettlementDTO;
import cn.stylefeng.guns.modular.business.frequency.financesettlement.model.param.FinanceSettlementParam;
import cn.stylefeng.guns.modular.business.frequency.financesettlement.model.result.PkgFinanceSettlementExport;
import cn.stylefeng.guns.modular.business.frequency.financesettlement.service.FinanceSettlementService;
import cn.stylefeng.guns.modular.business.frequency.financesettlement.enums.FinanceSettlementExceptionEnum;
import cn.stylefeng.guns.modular.business.frequency.financesettlementimage.entity.FinanceSettlementImage;
import cn.stylefeng.guns.modular.business.frequency.financesettlementimage.mapper.FinanceSettlementImageMapper;
import cn.stylefeng.guns.modular.business.frequency.orderfinishimage.mapper.OrderFinishImageMapper;
import cn.stylefeng.guns.modular.business.frequency.orderfinishrecord.mapper.OrderFinishRecordMapper;
import cn.stylefeng.guns.modular.business.frequency.orderpayrecord.mapper.OrderPayRecordMapper;
import cn.stylefeng.guns.modular.business.frequency.ordersub.model.result.PkgOnlinePayRecord;
import cn.stylefeng.guns.modular.business.frequency.ordersub.model.result.PkgOrderFinishRecord;
import cn.stylefeng.guns.modular.business.util.BusinessUtil;
import cn.stylefeng.guns.modular.business.util.poi.ExcelFormat;
import cn.stylefeng.guns.modular.business.util.poi.ExcelUtils;
import cn.stylefeng.guns.sys.modular.dict.entity.SysDictData;
import cn.stylefeng.guns.sys.modular.dict.entity.SysDictType;
import cn.stylefeng.guns.sys.modular.dict.mapper.SysDictDataMapper;
import cn.stylefeng.guns.sys.modular.dict.mapper.SysDictTypeMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 订单财务结算表（日记账） 服务实现类
 *
 * @author yujie
 * @date 2023/05/09 17:17
 */
@Service
public class FinanceSettlementServiceImpl extends ServiceImpl<FinanceSettlementMapper, FinanceSettlement> implements FinanceSettlementService {


    @Resource
    private FinanceSettlementMapper financeSettlementMapper;
    @Resource
    private FinanceSettlementImageMapper financeSettlementImageMapper;
    @Resource
    private CmCityMapper cmCityMapper;
    @Resource
    private FinanceCheckMapper financeCheckMapper;
    @Resource
    private OrderFinishImageMapper orderFinishImageMapper;
    @Resource
    private OrderFinishRecordMapper orderFinishRecordMapper;
    @Resource
    private OrderPayRecordMapper orderPayRecordMapper;
    @Autowired
    private BusinessUtil businessUtil;

    @Override
    public PageResult<FinanceSettlement> page(FinanceSettlementParam financeSettlementParam) {

        // 构造条件
        LambdaQueryWrapper<FinanceSettlement> queryWrapper = new LambdaQueryWrapper<>();

        // 查询分页结果
        return new PageResult<>(this.page(PageFactory.defaultPage(), queryWrapper));
    }

    @Override
    public List<FinanceSettlement> list(FinanceSettlementParam financeSettlementParam) {

        // 构造条件
        LambdaQueryWrapper<FinanceSettlement> queryWrapper = new LambdaQueryWrapper<>();

        return this.list(queryWrapper);
    }

    @Override
    public void add(FinanceSettlementParam financeSettlementParam) {

        // 将dto转为实体
        FinanceSettlement financeSettlement = new FinanceSettlement();
        BeanUtil.copyProperties(financeSettlementParam, financeSettlement);

        this.save(financeSettlement);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(FinanceSettlementParam financeSettlementParam) {

        // 根据id查询实体
        FinanceSettlement financeSettlement = this.queryFinanceSettlement(financeSettlementParam);

        // 更新实体
        this.updateById(financeSettlement);

    }

    @Override
    public void edit(FinanceSettlementParam financeSettlementParam) {

        // 根据id查询实体
        FinanceSettlement financeSettlement = this.queryFinanceSettlement(financeSettlementParam);

        // 请求参数转化为实体
        BeanUtil.copyProperties(financeSettlementParam, financeSettlement);

        // 不能修改状态，用修改状态接口修改状态
        financeSettlement.setStatus(null);

        this.updateById(financeSettlement);
    }

    @Override
    public FinanceSettlement detail(FinanceSettlementParam financeSettlementParam) {
        return this.queryFinanceSettlement(financeSettlementParam);
    }

    @Override
    public void changeStatus(FinanceSettlementParam financeSettlementParam) {
        Long id = financeSettlementParam.getId();
        Integer status = financeSettlementParam.getStatus();
        // 更新枚举，更新只能更新未删除状态的
        LambdaUpdateWrapper<FinanceSettlement> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper
            .eq(FinanceSettlement::getId, id)
            .set(FinanceSettlement::getStatus, status);
        boolean update = this.update(updateWrapper);
        if (!update) {
            throw new ServiceException(StatusExceptionEnum.UPDATE_STATUS_ERROR);
        }
    }


    /**
     * 获取订单财务结算表（日记账）
     *
     * @author yujie
     * @since 2023/05/09 17:17
     */
    private FinanceSettlement queryFinanceSettlement(FinanceSettlementParam financeSettlementParam) {
        FinanceSettlement financeSettlement = this.getById(financeSettlementParam.getId());
        if (ObjectUtil.isEmpty(financeSettlement)) {
            throw new ServiceException(FinanceSettlementExceptionEnum.NOT_EXISTED);
        }
        return financeSettlement;
    }


    @Override
    public ResponseData getFinanceSettlementList(Page page, FinanceSettlementDTO financeSettlementDTO) {
        AndaPageResult pageResult = new AndaPageResult();
        Page<PkgFinanceSettlement> list = financeSettlementMapper.getFinanceSettlementList(page, financeSettlementDTO,businessUtil.getTenantId());
        pageResult.AndaPageResult(page,list);
        pageResult.setSummary(financeSettlementMapper.getFinanceSettlementSummary(financeSettlementDTO, businessUtil.getTenantId()));
        return ResponseData.andaSuccess(pageResult);
    }

    public boolean checkFinanceSettlementAdd(FinanceSettlement financeSettlement, StringBuilder errorMsg) {
        return true;
    }

    @Transactional
    @Override
    public void addFinanceSettlement(FinanceSettlement financeSettlement) {
        financeSettlement.setSettlementTime(financeSettlement.getSettlementTime());
        financeSettlement.setResult(PublicCommon.待审核);
        financeSettlement.setCreateTime(new Date());
        financeSettlement.setCreateUser(LoginContextHolder.me().getSysLoginUserId().toString());
        financeSettlement.setUpdateTime(new Date());
        financeSettlement.setUpdateUser(LoginContextHolder.me().getSysLoginUserId().toString());
        financeSettlement.setTenantId(LoginContextHolder.me().getTenantId());
        financeSettlementMapper.insert(financeSettlement);
        // 图片
        if (financeSettlement.getImgList() != null && financeSettlement.getImgList().size() > 0) {
            for (String url : financeSettlement.getImgList()) {
                FinanceSettlementImage fsi = new FinanceSettlementImage();
                fsi.setSettlementId(financeSettlement.getId());
                fsi.setUrl(url);
                fsi.setTenantId(LoginContextHolder.me().getTenantId());
                financeSettlementImageMapper.insert(fsi);
            }
        }

    }

    @Autowired
    private SysDictTypeMapper sysDictTypeMapper;
    @Autowired
    private SysDictDataMapper sysDictDataMapper;

    public void exportExcel(FinanceSettlementDTO financeSettlementDTO, HttpServletResponse response) {
        //如果时间筛选条件不为空，进行格式转换
        timeTransfor(financeSettlementDTO);
        Page page = new Page();
        page.addOrder(OrderItem.desc("fs.settlement_time"));
        Page<PkgFinanceSettlement> list = financeSettlementMapper.getFinanceSettlementList(PageFactory.defaultPage(1,99999), financeSettlementDTO, businessUtil.getTenantId());
        // 财务打款渠道
        SysDictType channelType = sysDictTypeMapper.selectOne(new LambdaQueryWrapper<SysDictType>().eq(SysDictType::getTenantId, businessUtil.getTenantId()).eq(SysDictType::getCode, "finance_channel"));
        Map<String, String> channelMap = getChannelMap(channelType.getId());
        SysDictType subjectType = sysDictTypeMapper.selectOne(new LambdaQueryWrapper<SysDictType>().eq(SysDictType::getTenantId, businessUtil.getTenantId()).eq(SysDictType::getCode, "finance_customer_subject"));
        Map<String, String> subjectMap = getChannelMap(subjectType.getId());
        if (list != null && list.getRecords().size() > 0) {
            List<PkgFinanceSettlementExport> listExport = new ArrayList<>();
            for (PkgFinanceSettlement fs : list.getRecords()) {
                PkgFinanceSettlementExport export = new PkgFinanceSettlementExport();
                BeanUtils.copyProperties(fs, export);
                export.setSettlementTime(DateUtil.format(fs.getSettlementTime(),"yyyy-MM-dd HH:mm"));
                export.setCreateTime(DateUtil.format(fs.getCreateTime(),"yyyy-MM-dd HH:mm"));
                export.setTransportTime(DateUtil.format(fs.getTransportTime(),"yyyy-MM-dd HH:mm"));
                export.setOrderCreateTime(DateUtil.format(fs.getOrderCreateTime(),"yyyy-MM-dd HH:mm"));
                export.setChannelName(channelMap.get(fs.getChannel()));
                if(StringUtils.isNotBlank(fs.getCustomerSubject())){
                    export.setCustomerSubject(subjectMap.get(fs.getCustomerSubject()));
                }
                listExport.add(export);
            }

            List<ExcelHeaderInfo> headerInfos = Arrays.asList(
                    new ExcelHeaderInfo(0, 1, 0, 20, "日记账"));
            ExcelUtils excelUtils = new ExcelUtils(listExport, getHeadInfo(), headerInfos, getFormatInfo());
            excelUtils.sendHttpResponse(response, "日记账" + DateUtil.format(new Date(), "yyyy-MM-dd"), excelUtils.getWorkbook());
        }
    }

    private  Map<String, String> getChannelMap(Long typeId){
        List<Map<String, String>> maps = sysDictDataMapper.selectCodeAndValueAsMapByTypeId(typeId);
        Map<String, String> map = new HashMap<>();
        maps.stream().forEach(x->{
            map.put(x.get("code"),x.get("value"));
        });
        return map;
    }

    private static void timeTransfor(FinanceSettlementDTO financeSettlementDTO) {
        String beginSearchTime = financeSettlementDTO.getBeginSearchTime();
        String endSearchTime = financeSettlementDTO.getEndSearchTime();
        if (StringUtils.isNotEmpty(beginSearchTime)) {
            Date date = new Date(Long.parseLong(beginSearchTime));
            financeSettlementDTO.setBeginSearchTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date));
        }
        if (StringUtils.isNotEmpty(endSearchTime)) {
            Date date = new Date(Long.parseLong(endSearchTime));
            financeSettlementDTO.setEndSearchTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date));
        }

        String operatorBeginSearchTime = financeSettlementDTO.getOperatorBeginSearchTime();
        String operatorEndSearchTime = financeSettlementDTO.getOperatorEndSearchTime();
        if (StringUtils.isNotEmpty(operatorBeginSearchTime)) {
            Date date = new Date(Long.parseLong(operatorBeginSearchTime));
            financeSettlementDTO.setOperatorBeginSearchTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date));
        }
        if (StringUtils.isNotEmpty(operatorEndSearchTime)) {
            Date date = new Date(Long.parseLong(operatorEndSearchTime));
            financeSettlementDTO.setOperatorEndSearchTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date));
        }
    }

    private Map<String, ExcelFormat> getFormatInfo() {
        Map<String, ExcelFormat> format = new HashMap<>();
        format.put("collectionFee", ExcelFormat.FORMAT_NUMBER);
        format.put("paymentFee", ExcelFormat.FORMAT_NUMBER);
        format.put("balanceFee", ExcelFormat.FORMAT_NUMBER);
        format.put("orderCreateTime", ExcelFormat.FORMAT_DATE);
        format.put("transportTime", ExcelFormat.FORMAT_DATE);
        format.put("settlementTime", ExcelFormat.FORMAT_DATE);
        format.put("createTime", ExcelFormat.FORMAT_DATE);
        format.put("type", ExcelFormat.FORMAT_FINANCE_TYPE);
        format.put("channel", ExcelFormat.FORMAT_FINANCE_CHANNEL);
        // format.put("customerSubject", ExcelFormat.FORMAT_FINANCE_CUSTOMER_SUBJECT);
        return format;
    }

    private List<ExcelHeaderInfo> getHeadInfo() {
        return Arrays.asList(
                new ExcelHeaderInfo(2, 2, 0, 0, "子订单号"),
                new ExcelHeaderInfo(2, 2, 1, 1, "制单时间"),
                new ExcelHeaderInfo(2, 2, 2, 2, "制单人"),
                new ExcelHeaderInfo(2, 2, 3, 3, "运单号"),
                new ExcelHeaderInfo(2, 2, 4, 4, "发运时间"),
                new ExcelHeaderInfo(2, 2, 5, 5, "发运人"),
                new ExcelHeaderInfo(2, 2, 6, 6, "结算人"),
                new ExcelHeaderInfo(2, 2, 7, 7, "出发地"),
                new ExcelHeaderInfo(2, 2, 8, 8, "目的地"),
                new ExcelHeaderInfo(2, 2, 9, 9, "车型"),
                new ExcelHeaderInfo(2, 2, 10, 10, "车架号"),
                new ExcelHeaderInfo(2, 2, 11, 11, "费用类型"),
                new ExcelHeaderInfo(2, 2, 12, 12, "收款"),
                new ExcelHeaderInfo(2, 2, 13, 13, "付款"),
                new ExcelHeaderInfo(2, 2, 14, 14, "余额"),
                new ExcelHeaderInfo(2, 2, 15, 15, "结算时间"),
                new ExcelHeaderInfo(2, 2, 16, 16, "操作时间"),
                new ExcelHeaderInfo(2, 2, 17, 17, "渠道"),
                new ExcelHeaderInfo(2, 2, 18, 18, "费用科目"),
                new ExcelHeaderInfo(2, 2, 19, 19, "操作人"),
                new ExcelHeaderInfo(2, 2, 20, 20, "备注")
        );
    }

    @Override
    public PkgFinanceSettlement getFinanceSettlementDetail(String id) {
        PkgFinanceSettlement fs = financeSettlementMapper.getFinanceSettlementDetail(id);
        if (fs != null) {
            fs.setImgList(financeSettlementImageMapper.getSettlementImage(fs.getId()));
        }
        // 对账单结算图片处理
        if (fs.getOrigin() == 1 && StringUtils.isNotBlank(fs.getCheckId())) {
            FinanceCheck fc = financeCheckMapper.selectById(fs.getCheckId());
            fs.setImgList(new ArrayList<>(Arrays.asList(fc.getImages().split(","))));
        }
        // 到付 交付回单凭证处理
        if (fs.getType() == 2) {
            List<String> imgList = orderFinishImageMapper.getImageByOrderIdAndType(fs.getOrderId(), 2);
            fs.getImgList().addAll(imgList);
        }
        // 到付线上支付数据处理
        if (fs.getOrigin() == 2) {
            // 交付信息
            PkgOrderFinishRecord pkgOrderFinishRecord = orderFinishRecordMapper.getPkgOrderFinishRecordDetailByOrderId(fs.getOrderId());
            // 线上支付信息
            if (pkgOrderFinishRecord != null) {
                if (pkgOrderFinishRecord.getType() != null &&
                        pkgOrderFinishRecord.getType() == 1 && StringUtils.isNotBlank(pkgOrderFinishRecord.getClientSn())) {
                    PkgOnlinePayRecord onlinePayRecord = orderPayRecordMapper.getSuccessRecordByClientSn(pkgOrderFinishRecord.getClientSn());
                    fs.setOnlinePayData(onlinePayRecord);
                }
            }
        }
        return fs;
    }
}